<template>
  <div class="upload">
    <el-upload drag :action="uploadUrl()" :show-file-list="false" :on-success="handleAvatarSuccess" :before-upload="beforeAvatarUpload">
      <el-icon class="el-icon--upload"><upload-filled /></el-icon>
      <div class="el-upload__text">将文件拖到此处或点击上传</div>
      <template #tip>
        <p class="el-upload__tip">只能上传 {{ uploadTypes.join("、") }} 文件, 且不超过10M</p>
      </template>
    </el-upload>
  </div>
</template>

<script setup lang="ts">
/**
 * Upload.vue - 头像上传组件
 * 提供用户头像的上传功能，支持拖放和点击上传两种方式
 */
import { ref, computed } from "vue"; // Vue核心函数
import { useStore } from "vuex"; // Vuex状态管理
import { UploadFilled } from "@element-plus/icons-vue"; // 上传图标组件
import { HttpManager } from "@/api"; // API请求管理
import { ElMessage } from "element-plus"; // Element Plus消息提示组件

// 创建Vuex store实例
const store = useStore();

// 可上传的图片类型列表
const uploadTypes = ref(["jpg", "jpeg", "png", "gif"]);

// 计算属性：获取当前登录用户的ID
const userId = computed(() => store.getters.userId);

/**
 * 获取上传接口地址
 * @returns {string} 包含用户ID的上传接口URL
 */
function uploadUrl() {
  return HttpManager.uploadUrl(userId.value);
}

/**
 * 上传前的文件校验
 * @param {File} file - 要上传的文件对象
 * @returns {boolean} 文件是否符合上传条件
 */
function beforeAvatarUpload(file) {
  const ltCode = 2; // 最大允许上传的文件大小（MB）
  const isLt10M = file.size / 1024 / 1024; // 计算文件大小（MB）
  const fileType = file.type.replace(/image\//, ""); // 提取文件扩展名
  const isExistFileType = uploadTypes.value.includes(fileType); // 检查文件类型是否在允许列表中

  // 校验文件大小
  if (isLt10M > ltCode || isLt10M <= 0) {
    ElMessage.error(`图片大小范围是 0~${ltCode}MB!`);
  }
  // 校验文件类型
  if (!isExistFileType) {
    ElMessage.error(`图片只支持 ${uploadTypes.value.join("、")} 格式!`);
  }

  // 只有当文件大小和类型都符合要求时才返回true
  return isLt10M <= ltCode && isLt10M > 0 && isExistFileType;
}

/**
 * 上传成功后的处理函数
 * @param {ResponseBody} response - 服务器返回的响应数据
 * @param {File} file - 上传的文件对象
 */
function handleAvatarSuccess(response, file) {
  // 显示上传结果提示信息
  ElMessage({
    message: response.message,
    type: response.type,
  });

  // 如果上传成功，更新Vuex中的用户头像信息
  if (response.success) store.commit("setUserPic", response.data);
}
</script>

<style scoped>
.upload {
  width: 100%;
  height: 300px;
  display: flex;
  justify-content: center;
  align-items: center;
}
</style>
